﻿/**
 * @file		dd_ipcu.c
 * @brief		IPCU (Inter-Processor Communications Unit) driver
 * @note		None
 * @attention	None
 * 
 * <B><I>Copyright 2016 Socionext Inc.</I></B>
 */

#include <string.h>
#include "dd_ipcu.h"	
#include "ddim_user_custom.h"

/*----------------------------------------------------------------------*/
/* Definition															*/
/*----------------------------------------------------------------------*/
//---------------------------- driver section ----------------------------
#define D_DD_IPCU_MB_SPINLOCK		(D_DD_IPCU_MB_MAX)				/* Highest number for SpinLock reserved	*/
#define D_DD_IPCU_DATA_LENGTH		(36)							/* IPCU send data length				*/
#define D_DD_IPCU_MB_NOT_USE		(0xFF)							/* IPCU Mailbox not used 				*/
#define D_DD_IPCU_ID_MAX			(8)								/* total number of IPCU ID				*/
#define D_DD_IPCU_DATA_BLK_MAX		(9)								/* total number of IPCU send data		*/
#define D_DD_IPCU_SEND_DATA_MAX		(4 * D_DD_IPCU_DATA_BLK_MAX)	/* total number of IPCU data size		*/

#define D_DD_IPCU_MAGIC_NUMBER		(0xBEEFCAFEul)

#ifdef CO_DDIM_UTILITY_USE
//---------------------------- utility section ---------------------------
// Nothing Special
//---------------------------- colabo section ----------------------------
// Nothing Special

#endif //CO_DDIM_UTILITY_USE

/*----------------------------------------------------------------------*/
/* Enumeration															*/
/*----------------------------------------------------------------------*/
//---------------------------- driver section ----------------------------

#ifdef CO_DDIM_UTILITY_USE
//---------------------------- utility section ---------------------------
// Nothing Special
//---------------------------- colabo section ----------------------------
// Nothing Special

#endif //CO_DDIM_UTILITY_USE

/*----------------------------------------------------------------------*/
/* Structure															*/
/*----------------------------------------------------------------------*/
//---------------------------- driver section ----------------------------
/* IPCU Send information table */
typedef struct {
	UCHAR	ch;					/* IPCU ch					*/
	UCHAR	state;				/* State of IPCU process	*/
} T_DD_IPCU_SEND_INFO;

/* IPCU Request data */
typedef struct {
	ULONG	mb_data[D_DD_IPCU_MB_DATA_TOTAL_NUM];	/* Mailbox data */
} T_DD_IPCU_MB_DATA;

typedef VOID (*T_DD_IPCU_REQ_FUNC)(UCHAR, UCHAR*, UINT32, UINT32, UINT32);
typedef VOID (*T_DD_IPCU_RES_FUNC)(UCHAR, UCHAR*, UINT32);

#ifdef CO_DDIM_UTILITY_USE
//---------------------------- utility section ---------------------------
// Nothing Special
//---------------------------- colabo section ----------------------------
// Nothing Special

#endif //CO_DDIM_UTILITY_USE

/*----------------------------------------------------------------------*/
/* Global Data															*/
/*----------------------------------------------------------------------*/
//---------------------------- driver section ----------------------------
ULONG gIPCU_Spin_Lock __attribute__((section(".LOCK_SECTION"), aligned(64)));

#ifdef CO_DDIM_UTILITY_USE
//---------------------------- utility section ---------------------------
// Nothing Special
//---------------------------- colabo section ----------------------------
// Nothing Special

#endif //CO_DDIM_UTILITY_USE

/*----------------------------------------------------------------------*/
/* Macro																*/
/*----------------------------------------------------------------------*/
//---------------------------- driver section ----------------------------
// Nothing Special

#ifdef CO_DDIM_UTILITY_USE
//---------------------------- utility section ---------------------------
// Nothing Special
//---------------------------- colabo section ----------------------------
// Nothing Special

#endif //CO_DDIM_UTILITY_USE

/*----------------------------------------------------------------------*/
/* Local Method Definition												*/
/*----------------------------------------------------------------------*/
//---------------------------- driver section ----------------------------
// Nothing Special

#ifdef CO_DDIM_UTILITY_USE
//---------------------------- utility section ---------------------------
// Nothing Special
//---------------------------- colabo section ----------------------------
// Nothing Special

#endif //CO_DDIM_UTILITY_USE

/*----------------------------------------------------------------------*/
/* Local Function														*/
/*----------------------------------------------------------------------*/
//---------------------------- driver section ----------------------------
/* Nothing Special */

#ifdef CO_DDIM_UTILITY_USE
//---------------------------- utility section ---------------------------
// Nothing Special
//---------------------------- colabo section ----------------------------
// Nothing Special

#endif //CO_DDIM_UTILITY_USE

/*----------------------------------------------------------------------*/
/* Local Data                                                          */
/*----------------------------------------------------------------------*/
//---------------------------- driver section ----------------------------
static volatile VP_CALLBACK			gDD_IPCU_Ack_Func[D_DD_IPCU_MB_TOTAL_NUM] = {0};
static volatile VP_CALLBACK			gDD_IPCU_Req_Func[D_DD_IPCU_MB_TOTAL_NUM] = {0};

//static volatile VP_CALLBACK gDD_L2C_Interrupt_Callback = NULL;		// L2C Callback Function Pointer

#ifdef CO_DDIM_UTILITY_USE
//---------------------------- utility section ---------------------------
// Nothing Special
//---------------------------- colabo section ----------------------------
// Nothing Special

#endif //CO_DDIM_UTILITY_USE

/*----------------------------------------------------------------------*/
/* Global Function														*/
/*----------------------------------------------------------------------*/
//---------------------------- driver section ----------------------------
/**
 * @brief	Set IPCU operation condition and callback function for designated IPCU unit and Mailbox.
 * @param	ULONG id	IPCU ID(0-7)
 * @param	T_DD_IPCU_MNG ipcu_mng
 * @return	D_DDIM_OK/D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Ctrl( UCHAR id, T_DD_IPCU_MNG const* const ipcu_mng )
{
	ULONG src_num;
	ULONG dst_num;
	ULONG mask_num;
	UCHAR data_idx;
	
	src_num = ipcu_mng -> src_ch_num;
	dst_num = ipcu_mng -> dst_ch_num;
	mask_num = ipcu_mng -> mask_ch_num;
	
#ifdef CO_PARAM_CHECK
	if( id >= D_DD_IPCU_ID_MAX ){
		Ddim_Assertion(( "Dd_IPCU_Ctrl() - IPCU ID No. exceeds the maximum. : ID = %d\n", id ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( ipcu_mng == NULL ){
		Ddim_Assertion(( "Dd_IPCU_Ctrl() - IPCU MNG Tbl address is NULL. ID = %d\n", id ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( ipcu_mng -> data_size > D_DD_IPCU_SEND_DATA_MAX ) {
		Ddim_Assertion(( "Dd_IPCU_Ctrl() - IPCU data size exceeds the maximum. : ID = %d, size = %d\n", id, ipcu_mng -> data_size ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( src_num > D_DD_IPCU_INT_MAX ) {
		Ddim_Assertion(( "Dd_IPCU_Ctrl() - IPCU Source Interrupt Ch is out of range. : ID = %d, src_ch_num = %d\n", id, src_num ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( dst_num > D_DD_IPCU_INT_MAX ) {
		Ddim_Assertion(( "Dd_IPCU_Ctrl() - IPCU Source Interrupt Ch is out of range. : ID = %d, dst_ch_num = %d\n", id, dst_num ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( mask_num > D_DD_IPCU_INT_MAX ) {
		Ddim_Assertion(( "Dd_IPCU_Ctrl() - IPCU Interrupt mask Ch is out of range. : ID = %d, mask_ch_num = %d\n", id, mask_num ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	/* Set Mailbox */
	IO_IPCU1.MAILBOX[id].SRC.word = ( 1 << src_num );
	
	if( IO_IPCU1.MAILBOX[id].SRC.word != ( 1 << src_num )) {
		return D_DD_IPCU_MB_BUSY;
	}
	/* Set destination */
	IO_IPCU1.MAILBOX[id].DSTSET.word = ( 1 << dst_num );
	/* Set mask */
	IO_IPCU1.MAILBOX[id].MASKSET.word = ( 1 << mask_num );
	/* Set Mode */
	IO_IPCU1.MAILBOX[id].MODE.bit.MODE = ipcu_mng -> mode;
	/* Set data */
	for( data_idx = 0; data_idx < D_DD_IPCU_MB_DATA_TOTAL_NUM; data_idx++ ){
		IO_IPCU1.MAILBOX[id].DATA[data_idx] = ipcu_mng -> send_data[data_idx];
	}
	
	/* Set Ack callback function */
	gDD_IPCU_Ack_Func[id] = ipcu_mng->ack_func;
	
	/* Set Req callback function */
	gDD_IPCU_Req_Func[id] = ipcu_mng->req_func;
	
	return D_DDIM_OK;
}

/**
 * @brief	Get IPCU operation condition and callback function for designated IPCU unit and Mailbox.
 * @param	UCHAR id	IPCU ID(0-7)
 * @param	T_DD_IPCU_MNG *ipcu_mng
 * @return	D_DDIM_OK/D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Get_Ctrl( UCHAR id, T_DD_IPCU_MNG *const ipcu_mng )
{
	UCHAR src_cnt;
	UCHAR data_idx;
	
#ifdef CO_PARAM_CHECK
	if( id >= D_DD_IPCU_ID_MAX ) {
		Ddim_Assertion(( "Dd_IPCU_Get_Ctrl() - IPCU ID No. exceeds the maximum. : ID = %d\n", id ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( ipcu_mng == NULL ){
		Ddim_Assertion(( "Dd_IPCU_Get_Ctrl() - IPCU MNG Tbl address is NULL. ID = %d\n", id ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	/* Get source */
	for( src_cnt = 0; src_cnt < D_DD_IPCU_ID_MAX; src_cnt++ ){
		if(1 & (IO_IPCU1.MAILBOX[id].SRC.word >> ( src_cnt ))) {
			ipcu_mng -> src_ch_num = src_cnt;
		}
	}
	/* Get destination */
	ipcu_mng -> dst_ch_num = IO_IPCU1.MAILBOX[id].DSTSTAT.word;
	/* Get mask */
	ipcu_mng -> mask_ch_num = IO_IPCU1.MAILBOX[id].MASKSTAT.word;
	/* Get mode */
	ipcu_mng -> mode = IO_IPCU1.MAILBOX[id].MODE.bit.MODE;
	/* Get data */
	for( data_idx = 0; data_idx < D_DD_IPCU_MB_DATA_TOTAL_NUM; data_idx++ ){
		ipcu_mng -> send_data[data_idx] = IO_IPCU1.MAILBOX[id].DATA[data_idx];
	}
	
	ipcu_mng -> ack_func = gDD_IPCU_Ack_Func[id];
	ipcu_mng -> req_func = gDD_IPCU_Req_Func[id];

	return D_DDIM_OK;
}
/**
 * @brief	Start sending data.
 * @param	UCHAR id	IPCU ID(0-7)
 * @param	UCHAR state	IPCU state
 * @return	D_DDIM_OK/D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Start( UCHAR id, UCHAR state )
{
#ifdef CO_PARAM_CHECK
	if( id >= D_DD_IPCU_ID_MAX ) {
		Ddim_Assertion(( "Dd_IPCU_Start() - IPCU ID No. exceeds the maximum. : ID = %d, State = %d\n", id, state ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	/* Set start register */
	IO_IPCU1.MAILBOX[id].SEND.bit.SEND = 1;
	
	return D_DDIM_OK;
}

/**
 * @brief	Interrupt Handler of IPCU request or acknowledge.
 * @param	UINT32 int_ch	Interrupt ch of IPCU(12-15)
 */
VOID Dd_IPCU_Int_Handler( UINT32 int_ch )
{
	ULONG mb_num;
	
	UINT32 index = int_ch - 12;
	
	// Check Interrupt.
	if( IO_IPCU1.MBADR[index].bit.MBA == 0 ) {
		return;
	}
	
	/* Get Mail Box Number */
	mb_num = ( IO_IPCU1.MBADR[index].bit.MBA - 0x100 ) >> 7;
	
	/* Check ACK interrupt */
	if( IO_IPCU1.MBADR[index].bit.ACK ) {
		/* ACK interrupt callback */
		if( gDD_IPCU_Ack_Func[mb_num] ) {
			/* Callback function */
			( *gDD_IPCU_Ack_Func[mb_num] )( int_ch );
		}
	}
	
	/* Check Request interrupt */
	if( IO_IPCU1.MBADR[index].bit.REQ ) {
		/* Request interrupt callback */
		if( gDD_IPCU_Req_Func[mb_num] ) {
			/* Callback function */
			( *gDD_IPCU_Req_Func[mb_num] )( int_ch );
		}
	}
}

/**
 * @brief	Set Acknowledge callback function.
 * @param	UCHAR id	IPCU ID(0-7)
 * @param	VP_CALLBACK p_callback Callback function of Acknowledge
 * @return	D_DDIM_OK/D_DD_IPCU_INPUT_PARAM_ERR/D_DD_IPCU_STATUS_ABNORMAL
 */
INT32 Dd_IPCU_Set_Ack_CB( UCHAR id, VP_CALLBACK p_callback )
{
#ifdef CO_PARAM_CHECK
	if( id >= D_DD_IPCU_ID_MAX ) {
		Ddim_Print(( "Dd_IPCU_Set_Ack_CB() - IPCU ID No. exceeds the maximum. : ID = %d\n", id ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	gDD_IPCU_Ack_Func[id] = p_callback;
	
	return D_DDIM_OK;
}

/**
 * @brief	Set Request callback function.
 * @param	UCHAR id	IPCU ID(0-7)
 * @param	VP_CALLBACK p_callback	Callback function of Request
 * @return	D_DDIM_OK/D_DD_IPCU_INPUT_PARAM_ERR/D_DD_IPCU_STATUS_ABNORMAL
 */
INT32 Dd_IPCU_Set_Req_CB( UCHAR id, VP_CALLBACK p_callback )
{
#ifdef CO_PARAM_CHECK
	if( id >= D_DD_IPCU_ID_MAX ) {
		Ddim_Print(( "Dd_IPCU_Set_Req_CB() - IPCU ID No. exceeds the maximum. : ID = %d\n", id ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	gDD_IPCU_Req_Func[id] = p_callback;
	
	return D_DDIM_OK;
}

/*##################################
  ##   Interrupt Status Register  ##
  ##################################*/

/**
 * @brief	Get Interrupt Status
 * @param	UCHAR ch		Interrupt ch of IPCU(12-15)
 * @param	ULONG *state	Interrupt Status of IPCU
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Get_Int_Stat( UCHAR ch, ULONG *state )
{
#ifdef CO_PARAM_CHECK
	if( ch > D_DD_IPCU_INT_MAX ){
		Ddim_Print(( "Dd_IPCU_Get_Int_Stat() - INT Ch No is out of range. : Ch = %d\n", ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( state == NULL ){
		Ddim_Print(( "Dd_IPCU_Get_Int_Stat() - State address is NULL. : Ch = %d\n", ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	UINT32 index = ch - 12;
	
	*state = IO_IPCU1.ISR[index].word;
	
	return D_DDIM_OK;
}

/**
 * @brief	Get Interrupt Status indicated by Mailbox number
 * @param	UCHAR ch		Interrupt ch of IPCU(12-15)
 * @param	UCHAR mb_num 	Mailbox number
 * @param	ULONG *state	Interrupt Status of IPCU
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Get_Int_Stat_MB( UCHAR ch, UCHAR mb_num, ULONG *state )
{
#ifdef CO_PARAM_CHECK
	if( ch > D_DD_IPCU_INT_MAX ){
		Ddim_Print(( "Dd_IPCU_Get_Int_Stat_MB() - INT Ch No is out of range. : Ch = %d\n", ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( mb_num >= E_DD_IPCU_MB_ENABLE_MAX ){
		Ddim_Print(( "Dd_IPCU_Get_Int_Stat_MB() - IPCU Mailbox No. exceeds the maximum. : Ch = %d Bit = %d\n", ch, mb_num));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( state == NULL ){
		Ddim_Print(( "Dd_IPCU_Get_Int_Stat_MB() - State address is NULL.\n" ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	UINT32 index = ch - 12;
	
	*state = ( 1 & (IO_IPCU1.ISR[index].word >> ( mb_num )));
	
	return D_DDIM_OK;
}

/*##################################
  ##   Mailbox Address Register   ##
  ##################################*/
/**
 * @brief	Get Acknowledge status
 * @param	UCHAR ch	Interrupt ch of IPCU(12-15)
 * @param	ULONG *ack  Acknowledge(0:not Ack, 1:Ack)
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Get_MB_Ack( UCHAR ch, ULONG *ack )
{
#ifdef CO_PARAM_CHECK
	if( ch > D_DD_IPCU_INT_MAX ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Ack() - INT Ch No is out of range. : Ch = %d\n", ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( ack == NULL ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Ack() - Ack address is NULL. : Ch = %d\n", ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	UINT32 index = ch - 12;
	
	*ack = IO_IPCU1.MBADR[index].bit.ACK;
	
	return D_DDIM_OK;
}

/**
 * @brief	Get Request status
 * @param	UCHAR ch	Interrupt ch of IPCU(12-15)
 * @param	ULONG *req  Request(0:not Req, 1:Req)
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Get_MB_Req( UCHAR ch, ULONG *req )
{
#ifdef CO_PARAM_CHECK
	if( ch > D_DD_IPCU_INT_MAX ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Req() - INT Ch No is out of range. : Ch = %d\n", ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( req == NULL ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Req() - Req address is NULL. : Ch = %d\n", ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	UINT32 index = ch - 12;
	
	*req = IO_IPCU1.MBADR[index].bit.REQ;
	
	return D_DDIM_OK;
}

/**
 * @brief	Get Mailbox Address
 * @param	UCHAR ch	Interrupt ch of IPCU(12-15)
 * @param	ULONG *mba  Mailbox Address
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Get_MB_Adr( UCHAR ch, ULONG *mba )
{
#ifdef CO_PARAM_CHECK
	if( ch > D_DD_IPCU_INT_MAX ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Adr() - INT Ch No is out of range. : Ch = %d\n", ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( mba == NULL ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Adr() - Mailbox address is NULL. Ch = %d\n", ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	UINT32 index = ch - 12;
	
	*mba = IO_IPCU1.MBADR[index].bit.MBA;
	
	return D_DDIM_OK;
}

/*##################################
  ##   	    Source Register       ##
  ##################################*/
/**
 * @brief	Get Source information
 * @param	ULONG num	Mailbox number(0-7)
 * @param	ULONG *src  Request transmit source
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Get_MB_Src( ULONG num, ULONG *src )
{
#ifdef CO_PARAM_CHECK
	if( num > D_DD_IPCU_MB_MAX ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Src() - Mailbox number exceeds the maximum. : Num = %d\n", num));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( src == NULL ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Src() - Mailbox address is NULL. : Num = %d\n", num));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	*src = IO_IPCU1.MAILBOX[num].SRC.word;
	
	return D_DDIM_OK;
}

/**
 * @brief	Get Source information indicated by IPCU ch
 * @param	ULONG num		Mailbox number(0-7)
 * @param	UCHAR src_ch	Interrupt ch of IPCU(12-15)
 * @param	ULONG *src  	Request transmit source
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Get_MB_Src_Unit( ULONG num, UCHAR src_ch, ULONG *src )
{
#ifdef CO_PARAM_CHECK
	if( num > D_DD_IPCU_MB_MAX ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Src_Unit() - Mailbox number exceeds the maximum. : Num = %d, Ch = %d\n", num, src_ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( src_ch > D_DD_IPCU_INT_MAX ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Src_Unit() - INT Ch No is out of range. : Num = %d Ch = %d\n", num, src_ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( src == NULL ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Src_Unit() - Mailbox address is NULL. : Num = %d, Ch = %d\n", num, src_ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	*src = (1 & (IO_IPCU1.MAILBOX[num].SRC.word >> ( src_ch )));
	
	return D_DDIM_OK;
}

/**
 * @brief	Set Source information
 * @param	ULONG num	Mailbox number(0-7)
 * @param	ULONG src   Request transmit source
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Set_MB_Src( ULONG num, ULONG src )
{
#ifdef CO_PARAM_CHECK
	if( num > D_DD_IPCU_MB_MAX ){
		Ddim_Print(( "Dd_IPCU_Set_MB_Src() - Mailbox number exceeds the maximum. : Num = %d\n", num ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	IO_IPCU1.MAILBOX[num].SRC.word = src;
	
	return D_DDIM_OK;
}

/*##################################
  ##        Mode Register         ##
  ##################################*/
/**
 * @brief	Get Mode information
 * @param	ULONG num	Mailbox number(0-7)
 * @param	ULONG *mode Operation mode
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Get_MB_Mode( ULONG num, ULONG *mode )
{
#ifdef CO_PARAM_CHECK
	if( num > D_DD_IPCU_MB_MAX ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Mode() - Mailbox number exceeds the maximum. : Num = %d\n", num ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( mode == NULL ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Mode() - Mode address is NULL. : Num = %d\n", num ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	*mode = IO_IPCU1.MAILBOX[num].MODE.bit.MODE;
	
	return D_DDIM_OK;
}

/**
 * @brief	Set Mode information
 * @param	ULONG num				Mailbox number(0-7)
 * @param	E_DD_IPCU_MB_MODE mode  Operation mode
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Set_MB_Mode( ULONG num, E_DD_IPCU_MB_MODE mode )
{
#ifdef CO_PARAM_CHECK
	if( num > D_DD_IPCU_MB_MAX ){
		Ddim_Print(( "Dd_IPCU_Set_MB_Mode() - Mailbox number exceeds the maximum. : Num = %d\n", num ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( mode >= E_DD_IPCU_MB_MODE_MAX ){
		Ddim_Print(( "Dd_IPCU_Set_MB_Mode() - Mode address is NULL. : Num = %d\n", num ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	IO_IPCU1.MAILBOX[num].MODE.bit.MODE = mode;
	
	return D_DDIM_OK;
}

/*##################################
  ##        Send Register         ##
  ##################################*/
/**
 * @brief	Get Send trigger
 * @param	ULONG num	Mailbox number(0-7)
 * @param	ULONG *send Send trigger
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Get_MB_Send( ULONG num, ULONG *send )
{
#ifdef CO_PARAM_CHECK
	if( num > D_DD_IPCU_MB_MAX ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Send() - Mailbox number exceeds the maximum. : Num = %d\n", num ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( send == NULL ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Send() - Send address is NULL. : Num = %d\n", num ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	*send = IO_IPCU1.MAILBOX[num].SEND.bit.SEND;
	
	return D_DDIM_OK;
}

/**
 * @brief	Set Send trigger
 * @param	ULONG num	Mailbox number(0-7)
 * @param	ULONG send 	Send trigger
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Set_MB_Send( ULONG num, ULONG send )
{
#ifdef CO_PARAM_CHECK
	if( num > D_DD_IPCU_MB_MAX ){
		Ddim_Print(( "Dd_IPCU_Set_MB_Send() - Mailbox number exceeds the maximum. : Num = %d\n", num ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	if( IO_IPCU1.MAILBOX[num].SRC.word == 0) {
		Ddim_Print(( "Dd_IPCU_Set_MB_Send() - Request transmit source is not set. : Num = %d\n", num ));
		return D_DD_IPCU_STATUS_ABNORMAL;
	}
	
	IO_IPCU1.MAILBOX[num].SEND.bit.SEND = send;
	
	return D_DDIM_OK;
}

/*##################################
  ##  Destination Set Register    ##
  ##################################*/
/**
 * @brief	Set Destination information
 * @param	ULONG num	Mailbox number(0-7)
 * @param	ULONG dst 	Request transmit destination
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Set_MB_Dst( ULONG num, ULONG dst )
{
#ifdef CO_PARAM_CHECK
	if( num > D_DD_IPCU_MB_MAX ){
		Ddim_Print(( "Dd_IPCU_Set_MB_Dst() - Mailbox number exceeds the maximum. : Num = %d\n", num ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	/* Check Sourece register */
	if( IO_IPCU1.MAILBOX[num].SRC.word == 0) {
		Ddim_Print(( "Dd_IPCU_Set_MB_Dst() - Request transmit source is not set. : Num = %d\n", num ));
		return D_DD_IPCU_STATUS_ABNORMAL;
	}
	/* Check Send register */
	if( IO_IPCU1.MAILBOX[num].SEND.bit.SEND != 0) {
		Ddim_Print(( "Dd_IPCU_Set_MB_Dst() - Send trigger is set. : Num = %d\n", num ));
		return D_DD_IPCU_STATUS_ABNORMAL;
	}
	
	IO_IPCU1.MAILBOX[num].DSTSET.word = dst;
	
	return D_DDIM_OK;
}

/**
 * @brief	Set Destination information indicated by IPCU ch
 * @param	ULONG num		Mailbox number(0-7)
 * @param	ULONG dst_ch 	Request transmit destination ch(12-15)
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Set_MB_Dst_Unit( ULONG num, ULONG dst_ch )
{
#ifdef CO_PARAM_CHECK
	if( num > D_DD_IPCU_MB_MAX ){
		Ddim_Print(( "Dd_IPCU_Set_MB_Dst_Unit() - Mailbox number exceeds the maximum. : Num = %d Ch = %d\n", num, dst_ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( dst_ch > D_DD_IPCU_INT_MAX ){
		Ddim_Print(( "Dd_IPCU_Set_MB_Dst_Unit() - INT Ch No is out of range. : Num = %d Ch = %d\n", num, dst_ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	/* Check Sourece register */
	if( IO_IPCU1.MAILBOX[num].SRC.word == 0) {
		Ddim_Print(( "Dd_IPCU_Set_MB_Dst_Unit() - Request transmit source is not set. : Num = %d Ch = %d\n", num, dst_ch ));
		return D_DD_IPCU_STATUS_ABNORMAL;
	}
	/* Check Send register */
	if( IO_IPCU1.MAILBOX[num].SEND.bit.SEND != 0) {
		Ddim_Print(( "Dd_IPCU_Set_MB_Dst_Unit() - Send trigger is set. : Num = %d Ch = %d\n", num, dst_ch ));
		return D_DD_IPCU_STATUS_ABNORMAL;
	}
	
	IO_IPCU1.MAILBOX[num].DSTSET.word = (1U << (dst_ch));
	
	return D_DDIM_OK;
}

/*##################################
  ##  Destination Clear Register  ##
  ##################################*/
/**
 * @brief	Clear Destination information
 * @param	ULONG num	Mailbox number(0-7)
 * @param	ULONG dst 	Request transmit destination by bit data
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Clr_MB_Dst( ULONG num, ULONG dst )
{
	UCHAR loop_cnt;
	UCHAR bit_cnt = 0;
	
#ifdef CO_PARAM_CHECK
	if( num > D_DD_IPCU_MB_MAX ){
		Ddim_Print(( "Dd_IPCU_Clr_MB_Dst() - Mailbox number exceeds the maximum. : Num = %d, Dst = %lu\n", num, dst ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	
	for( loop_cnt = 0; loop_cnt <= D_DD_IPCU_INT_MAX; loop_cnt++ ) {
		if( 1 & ( dst >> loop_cnt )) {
			bit_cnt++;
		}
	}
	if( bit_cnt > 1 ){
		Ddim_Print(( "Dd_IPCU_Clr_MB_Dst() - Too many setting bits. : Num = %d, Dst = %lu\n", num, dst ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	
#endif // CO_PARAM_CHECK
	
	/* Check Sourece register */
	if( IO_IPCU1.MAILBOX[num].SRC.word == 0) {
		Ddim_Print(( "Dd_IPCU_Clr_MB_Dst() - Request transmit source is not set. : Num = %d, Dst = %lu\n", num, dst ));
		return D_DD_IPCU_STATUS_ABNORMAL;
	}
	/* Check Destination Status register */
	if( dst == ( IO_IPCU1.MAILBOX[num].DSTSTAT.word & dst )) {
		Ddim_Print(( "Dd_IPCU_Clr_MB_Dst() - Request for designated ch is nothing. : Num = %d, Dst = %lu\n", num, dst ));
		return D_DD_IPCU_STATUS_ABNORMAL;
	}
	
	IO_IPCU1.MAILBOX[num].DSTCLR.word = dst;
	
	return D_DDIM_OK;
}

/**
 * @brief	Clear Destination information indicated by IPCU ch
 * @param	ULONG num		Mailbox number(0-7)
 * @param	ULONG dst_ch 	Request transmit destination ch(12-15)
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Clr_MB_Dst_Unit( ULONG num, UCHAR dst_ch )
{
#ifdef CO_PARAM_CHECK
	if( num > D_DD_IPCU_MB_MAX ){
		Ddim_Print(( "Dd_IPCU_Clr_MB_Dst_Unit() - Mailbox number exceeds the maximum. : Num = %d Ch = %d\n", num, dst_ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( dst_ch > D_DD_IPCU_INT_MAX ){
		Ddim_Print(( "Dd_IPCU_Clr_MB_Dst_Unit() - INT Ch No is out of range. : Num = %d Ch = %d\n", num, dst_ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	/* Check Sourece register */
	if( IO_IPCU1.MAILBOX[num].SRC.word == 0) {
		Ddim_Print(( "Dd_IPCU_Clr_MB_Dst_Unit() - Request transmit source is not set. :Num = %d Ch = %d\n", num, dst_ch ));
		return D_DD_IPCU_STATUS_ABNORMAL;
	}
	/* Check Destination Status register */
	if(( 1 & (IO_IPCU1.MAILBOX[num].DSTSTAT.word >> dst_ch)) == 0 ) {
		Ddim_Print(( "Dd_IPCU_Clr_MB_Dst_Unit() - Request for designated ch is nothing. : Num = %d Ch = %d\n", num, dst_ch ));
		return D_DD_IPCU_STATUS_ABNORMAL;
	}
	IO_IPCU1.MAILBOX[num].DSTCLR.word = (1U << (dst_ch));
	
	return D_DDIM_OK;
}

/*##################################
  ##  Destination Status Register ##
  ##################################*/
/**
 * @brief	Get Destination information
 * @param	ULONG num	Mailbox number(0-7)
 * @param	ULONG *dst 	Request transmit destination
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Get_MB_Dst_Stat( ULONG num, ULONG *dst )
{
#ifdef CO_PARAM_CHECK
	if( num > D_DD_IPCU_MB_MAX ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Dst_Stat() - Mailbox number exceeds the maximum. : Num = %d\n", num ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( dst == NULL ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Dst_Stat() - Dst address is NULL. : Num = %d\n", num ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	*dst = IO_IPCU1.MAILBOX[num].DSTSTAT.word;
	
	return D_DDIM_OK;
}

/**
 * @brief	Get Destination information indicated by IPCU ch
 * @param	ULONG num	Mailbox number(0-7)
 * @param	UCHAR ch	Interrupt ch of IPCU(12-15)
 * @param	ULONG *dst 	Request transmit destination
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Get_MB_Dst_Stat_Unit( ULONG num, UCHAR dst_ch, ULONG *dst )
{
#ifdef CO_PARAM_CHECK
	if( num > D_DD_IPCU_MB_MAX ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Dst_Stat_Unit() - Mailbox number exceeds the maximum. : Num = %d Ch = %d\n", num, dst_ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( dst_ch > D_DD_IPCU_INT_MAX ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Dst_Stat_Unit() - INT Ch No is out of range. : Num = %d Ch = %d\n", num, dst_ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( dst == NULL ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Dst_Stat_Unit() - Dst address is NULL. : Num = %d Ch = %d\n", num, dst_ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	*dst = (1 & (IO_IPCU1.MAILBOX[num].DSTSTAT.word >> ( dst_ch )));
	
	return D_DDIM_OK;
}

/*##################################
  ##       Mask Set Register      ##
  ##################################*/
/**
 * @brief	Set Mask request
 * @param	ULONG num	Mailbox number(0-7)
 * @param	ULONG msk 	Mask request
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Set_MB_Msk( ULONG num, ULONG msk )
{
#ifdef CO_PARAM_CHECK
	if( num > D_DD_IPCU_MB_MAX ){
		Ddim_Print(( "Dd_IPCU_Set_MB_Msk() - Mailbox number exceeds the maximum. : Num = %d\n", num ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	/* Check Sourece register */
	if( IO_IPCU1.MAILBOX[num].SRC.word == 0) {
		Ddim_Print(( "Dd_IPCU_Set_MB_Msk() - Request transmit source is not set. : Num = %d\n", num ));
		return D_DD_IPCU_STATUS_ABNORMAL;
	}
	/* Check Send register */
	if( IO_IPCU1.MAILBOX[num].SEND.bit.SEND != 0) {
		Ddim_Print(( "Dd_IPCU_Set_MB_Msk() - Send trigger is set. : Num = %d\n", num ));
		return D_DD_IPCU_STATUS_ABNORMAL;
	}
	
	IO_IPCU1.MAILBOX[num].MASKSET.word = msk;
	
	return D_DDIM_OK;
}

/**
 * @brief	Set Mask request indicated by IPCU ch
 * @param	ULONG num		Mailbox number(0-7)
 * @param	ULONG msk_ch 	Request mask ch(12-15)
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Set_MB_Msk_Unit( ULONG num, ULONG msk_ch )
{
#ifdef CO_PARAM_CHECK
	if( num > D_DD_IPCU_MB_MAX ){
		Ddim_Print(( "Dd_IPCU_Set_MB_Msk_Unit() - Mailbox number exceeds the maximum. : Num = %d Ch = %d\n", num, msk_ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( msk_ch > D_DD_IPCU_INT_MAX ){
		Ddim_Print(( "Dd_IPCU_Set_MB_Msk_Unit() - INT Ch No is out of range. : Num = %d Ch = %d\n", num, msk_ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	/* Check Sourece register */
	if( IO_IPCU1.MAILBOX[num].SRC.word == 0) {
		Ddim_Print(( "Dd_IPCU_Set_MB_Msk_Unit() - Request transmit source is not set. : Num = %d Ch = %d\n", num, msk_ch ));
		return D_DD_IPCU_STATUS_ABNORMAL;
	}
	/* Check Send register */
	if( IO_IPCU1.MAILBOX[num].SEND.bit.SEND != 0) {
		Ddim_Print(( "Dd_IPCU_Set_MB_Msk_Unit() - Send trigger is set. : Num = %d Ch = %d\n", num, msk_ch ));
		return D_DD_IPCU_STATUS_ABNORMAL;
	}
	
	IO_IPCU1.MAILBOX[num].MASKSET.word = (1U << (msk_ch));
	
	return D_DDIM_OK;
}

/*##################################
  ##      Mask Clear Register     ##
  ##################################*/
/**
 * @brief	Clear Mask request indicated by IPCU ch
 * @param	ULONG num	Mailbox number(0-7)
 * @param	ULONG msk 	Mask request by bit data
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Clr_MB_Msk( ULONG num, ULONG msk )
{
#ifdef CO_PARAM_CHECK
	if( num > D_DD_IPCU_MB_MAX ){
		Ddim_Print(( "Dd_IPCU_Clr_MB_Msk() - Mailbox number exceeds the maximum. : Num = %d, Msk = %lu\n", num, msk ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	/* Check Sourece register */
	if( IO_IPCU1.MAILBOX[num].SRC.word == 0) {
		Ddim_Print(( "Dd_IPCU_Clr_MB_Msk() - Request transmit source is not set. : Num = %d, Msk = %lu\n", num, msk ));
		return D_DD_IPCU_STATUS_ABNORMAL;
	}
	
	IO_IPCU1.MAILBOX[num].MASKCLR.word = msk;
	
	return D_DDIM_OK;
}

/**
 * @brief	Clear Mask request
 * @param	ULONG num		Mailbox number(0-7)
 * @param	ULONG msk_ch 	Request mask ch(12-15)
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Clr_MB_Msk_Unit( ULONG num, ULONG msk_ch )
{
#ifdef CO_PARAM_CHECK
	if( num > D_DD_IPCU_MB_MAX ){
		Ddim_Print(( "Dd_IPCU_Clr_MB_Msk_Unit() - Mailbox number exceeds the maximum. : Num = %d Ch = %d\n", num, msk_ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( msk_ch > D_DD_IPCU_INT_MAX ){
		Ddim_Print(( "Dd_IPCU_Clr_MB_Msk_Unit() - INT Ch No is out of range. : Num = %d Ch = %d\n", num, msk_ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	/* Check Sourece register */
	if( IO_IPCU1.MAILBOX[num].SRC.word == 0) {
		Ddim_Print(( "Dd_IPCU_Clr_MB_Msk_Unit() - Request transmit source is not set. : Num = %d Ch = %d\n", num, msk_ch ));
		return D_DD_IPCU_STATUS_ABNORMAL;
	}
	
	IO_IPCU1.MAILBOX[num].MASKCLR.word = (1U << (msk_ch));
	
	return D_DDIM_OK;
}

/*##################################
  ##     Mask Status Register     ##
  ##################################*/
/**
 * @brief	Get Mask request status
 * @param	ULONG num	Mailbox number(0-7)
 * @param	ULONG *msk 	Mask request
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Get_MB_Msk_Stat( ULONG num, ULONG *msk )
{
#ifdef CO_PARAM_CHECK
	if( num > D_DD_IPCU_MB_MAX ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Msk_Stat() - Mailbox number exceeds the maximum. : Num = %d\n", num ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( msk == NULL ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Msk_Stat() - Msk address is NULL. : Num = %d\n", num ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	*msk = IO_IPCU1.MAILBOX[num].MASKSTAT.word;
	
	return D_DDIM_OK;
}

/**
 * @brief	Get Mask request indicated by IPCU ch
 * @param	ULONG num		Mailbox number(0-7)
 * @param	UCHAR msk_ch	Interrupt ch of IPCU(12-15)
 * @param	ULONG *msk	 	Mask request
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Get_MB_Msk_Stat_Unit( ULONG num, ULONG msk_ch, ULONG *msk )
{
#ifdef CO_PARAM_CHECK
	if( num > D_DD_IPCU_MB_MAX ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Msk_Stat_Unit() - Mailbox number exceeds the maximum. : Num = %d, Ch = %d\n", num, msk_ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( msk_ch > D_DD_IPCU_INT_MAX ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Msk_Stat_Unit() - INT Ch No is out of range. : Num = %d Ch = %d\n", num, msk_ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( msk == NULL ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Msk_Stat_Unit() - Msk address is NULL. : Num = %d, Ch = %d\n", num, msk_ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	*msk = (1 & (IO_IPCU1.MAILBOX[num].MASKSTAT.word >> ( msk_ch )));
	
	return D_DDIM_OK;
}

/*##################################
  ##    Acknowledge Set Register  ##
  ##################################*/
/**
 * @brief	Set Acknowledge
 * @param	ULONG num	Mailbox number(0-7)
 * @param	ULONG ack 	Acknowledge
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Set_MB_Ack( ULONG num, ULONG ack )
{
	UCHAR loop_cnt;
	UCHAR bit_cnt = 0;

#ifdef CO_PARAM_CHECK
	if( num > D_DD_IPCU_MB_MAX ){
		Ddim_Print(( "Dd_IPCU_Set_MB_Ack() - Mailbox number exceeds the maximum. : Num = %d\n", num ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( IO_IPCU1.MAILBOX[num].MODE.bit.MODE == E_DD_IPCU_MB_MODE_MANUAL_2 ) {
		/* Check too many setting */
		for( loop_cnt = 0; loop_cnt <= D_DD_IPCU_INT_MAX; loop_cnt++ ) {
			if( 1 & ( ack >> loop_cnt )) {
				bit_cnt++;
			}
		}
		if( bit_cnt > 1 ) {
			Ddim_Print(( "Dd_IPCU_Set_MB_Ack() - Too many setting bits. : Num = %d, Ack = %lu\n", num, ack ));
			return D_DD_IPCU_INPUT_PARAM_ERR;
		}
		/* Check status with mode 2 */
		if(( IO_IPCU1.MAILBOX[num].ACKSET.word & ack ) != 0 ) {
			Ddim_Print(( "Dd_IPCU_Set_MB_Ack() - Mailbox number exceeds the maximum. : Num = %d\n", num ));
			return D_DD_IPCU_INPUT_PARAM_ERR;
		}
	}
#endif // CO_PARAM_CHECK
	
	/* Check Sourece register */
	if( IO_IPCU1.MAILBOX[num].SRC.word == 0) {
		Ddim_Print(( "Dd_IPCU_Set_MB_Ack() - Request transmit source is not set. : Num = %d, Ack = %lu\n", num, ack ));
		return D_DD_IPCU_STATUS_ABNORMAL;
	}
	/* Check Send register */
	if( IO_IPCU1.MAILBOX[num].SEND.bit.SEND == 0) {
		Ddim_Print(( "Dd_IPCU_Set_MB_Ack() - Send trigger is not set. : Num = %d\n", num ));
		return D_DD_IPCU_STATUS_ABNORMAL;
	}
	/* Check mode type */
	if( IO_IPCU1.MAILBOX[num].MODE.bit.MODE > E_DD_IPCU_MB_MODE_MANUAL_2 ) {
		Ddim_Print(( "Dd_IPCU_Set_MB_Ack() - Mode is not correct. : Num = %d\n", num ));
		return D_DD_IPCU_STATUS_ABNORMAL;
	}
	
	IO_IPCU1.MAILBOX[num].ACKSET.word = ack;
	
	return D_DDIM_OK;
}

/**
 * @brief	Set Acknowledge indicated by IPCU ch
 * @param	ULONG num		Mailbox number(0-7)
 * @param	ULONG ack_ch 	Acknowledge ch(12-15)
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Set_MB_Ack_Unit( ULONG num, ULONG ack_ch )
{
#ifdef CO_PARAM_CHECK
	if( num > D_DD_IPCU_MB_MAX ){
		Ddim_Print(( "Dd_IPCU_Set_MB_Ack_Unit() - Mailbox number exceeds the maximum. : Num = %d\n", num ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( ack_ch > D_DD_IPCU_INT_MAX ){
		Ddim_Print(( "Dd_IPCU_Set_MB_Ack_Unit() - INT Ch No is out of range. : Num = %d Ch = %d\n", num, ack_ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( IO_IPCU1.MAILBOX[num].MODE.bit.MODE == E_DD_IPCU_MB_MODE_MANUAL_2 ) {
		/* Check status with mode 2 */
		if( 1 & (IO_IPCU1.MAILBOX[num].DSTSTAT.word >> ( ack_ch ))) {
			Ddim_Print(( "Dd_IPCU_Set_MB_Ack_Unit() - Mailbox number exceeds the maximum. : Num = %d Ch = %d\n", num, ack_ch ));
			return D_DD_IPCU_INPUT_PARAM_ERR;
		}
	}
#endif // CO_PARAM_CHECK
	
	/* Check Sourece register */
	if( IO_IPCU1.MAILBOX[num].SRC.word == 0) {
		Ddim_Print(( "Dd_IPCU_Set_MB_Ack_Unit() - Request transmit source is not set. : Num = %d, Ack = %d\n", num, ack_ch ));
		return D_DD_IPCU_STATUS_ABNORMAL;
	}
	/* Check Send register */
	if( IO_IPCU1.MAILBOX[num].SEND.bit.SEND == 0) {
		Ddim_Print(( "Dd_IPCU_Set_MB_Ack_Unit() - Send trigger is not set. : Num = %d\n", num ));
		return D_DD_IPCU_STATUS_ABNORMAL;
	}
	/* Check mode type */
	if( IO_IPCU1.MAILBOX[num].MODE.bit.MODE > E_DD_IPCU_MB_MODE_MANUAL_2 ) {
		Ddim_Print(( "Dd_IPCU_Set_MB_Ack_Unit() - Mode is not correct. : Num = %d\n", num ));
		return D_DD_IPCU_STATUS_ABNORMAL;
	}
	
	IO_IPCU1.MAILBOX[num].ACKSET.word = (1U << (ack_ch));
	
	return D_DDIM_OK;

}

/*##################################
  ##  Acknowledge Clear Register  ##
  ##################################*/
/**
 * @brief	Clear Acknowledge indicated by IPCU ch
 * @param	ULONG num	Mailbox number(0-7)
 * @param	ULONG msk 	Acknowledge by bit data
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Clr_MB_Ack( ULONG num, ULONG ack )
{
#ifdef CO_PARAM_CHECK
	if( num > D_DD_IPCU_MB_MAX ){
		Ddim_Print(( "Dd_IPCU_Clr_MB_Ack() - Mailbox number exceeds the maximum. : Num = %d, Ack = %lu\n", num, ack ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	/* Check Sourece register */
	if( IO_IPCU1.MAILBOX[num].SRC.word == 0) {
		Ddim_Print(( "Dd_IPCU_Clr_MB_Ack() - Request transmit source is not set. : Num = %d, Clr = %lu\n", num, ack ));
		return D_DD_IPCU_STATUS_ABNORMAL;
	}
	/* Check Send register */
	if( IO_IPCU1.MAILBOX[num].SEND.bit.SEND == 0) {
		Ddim_Print(( "Dd_IPCU_Clr_MB_Ack() - Send trigger is not set. : Num = %d\n", num ));
		return D_DD_IPCU_STATUS_ABNORMAL;
	}
	/* Check mode type */
	if( IO_IPCU1.MAILBOX[num].MODE.bit.MODE == E_DD_IPCU_MB_MODE_AUTO_CLEAR ) {
		Ddim_Print(( "Dd_IPCU_Clr_MB_Ack() - Mode is Auto clear mode. : Num = %d, Mode = %d\n", num ));
		return D_DD_IPCU_STATUS_ABNORMAL;
	}
	
	IO_IPCU1.MAILBOX[num].ACKCLR.word = ack;
	
	return D_DDIM_OK;
}

/**
 * @brief	Clear Acknowledge indicated by IPCU ch
 * @param	ULONG num		Mailbox number(0-7)
 * @param	ULONG ack_ch 	Acknowledge by bit data
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Clr_MB_Ack_Unit( ULONG num, ULONG ack_ch )
{
#ifdef CO_PARAM_CHECK
	if( num > D_DD_IPCU_MB_MAX ){
		Ddim_Print(( "Dd_IPCU_Clr_MB_Ack_Unit() - Mailbox number exceeds the maximum. : Num = %d, Ch = %lu\n", num, ack_ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( ack_ch > D_DD_IPCU_INT_MAX ){
		Ddim_Print(( "Dd_IPCU_Clr_MB_Ack_Unit() - INT Ch No is out of range. : Num = %d Ch = %d\n", num, ack_ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	/* Check Sourece register */
	if( IO_IPCU1.MAILBOX[num].SRC.word == 0) {
		Ddim_Print(( "Dd_IPCU_Clr_MB_Ack_Unit() - Request transmit source is not set. : Num = %d, Ch = %lu\n", num, ack_ch ));
		return D_DD_IPCU_STATUS_ABNORMAL;
	}
	/* Check Send register */
	if( IO_IPCU1.MAILBOX[num].SEND.bit.SEND == 0) {
		Ddim_Print(( "Dd_IPCU_Clr_MB_Ack_Unit() - Send trigger is not set. : Num = %d, Ch = %lu\n", num, ack_ch ));
		return D_DD_IPCU_STATUS_ABNORMAL;
	}
	/* Check mode type */
	if( IO_IPCU1.MAILBOX[num].MODE.bit.MODE == E_DD_IPCU_MB_MODE_AUTO_CLEAR ) {
		Ddim_Print(( "Dd_IPCU_Clr_MB_Ack_Unit() - Mode is Auto clear mode. : Num = %d, Ch = %lu\n", num, ack_ch ));
		return D_DD_IPCU_STATUS_ABNORMAL;
	}
	
	IO_IPCU1.MAILBOX[num].ACKCLR.word = (1U << (ack_ch));
	
	return D_DDIM_OK;
}

/*##################################
  ##  Acknowledge Status Register ##
  ##################################*/
/**
 * @brief	Get Acknowledge status
 * @param	ULONG num	Mailbox number(0-7)
 * @param	ULONG *ack 	Acknowledge status
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Get_MB_Ack_Stat( ULONG num, ULONG *ack )
{
#ifdef CO_PARAM_CHECK
	if( num > D_DD_IPCU_MB_MAX ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Ack_Stat() - Mailbox number exceeds the maximum. : Num = %d\n", num ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( ack == NULL ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Ack_Stat() - Ack address is NULL. : Num = %d\n", num ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	/* Check mode type */
	if( IO_IPCU1.MAILBOX[num].MODE.bit.MODE == E_DD_IPCU_MB_MODE_AUTO_CLEAR ) {
		Ddim_Print(( "Dd_IPCU_Get_MB_Ack_Stat() - Mode is not correct. : Num = %d\n", num ));
		return D_DD_IPCU_STATUS_ABNORMAL;
	}
	*ack = IO_IPCU1.MAILBOX[num].ACKSTAT.word;
	
	return D_DDIM_OK;
}

/**
 * @brief	Get Acknowledge indicated by IPCU ch
 * @param	ULONG num		Mailbox number(0-7)
 * @param	UCHAR ack_ch	Interrupt ch of IPCU(12-15)
 * @param	ULONG *ack	 	Acknowledge
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Get_MB_Ack_Stat_Unit( ULONG num, ULONG ack_ch, ULONG *ack )
{
#ifdef CO_PARAM_CHECK
	if( num > D_DD_IPCU_MB_MAX ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Ack_Stat_Unit() - Mailbox number exceeds the maximum. : Num = %d, Ch = %d\n", num, ack_ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( ack_ch > D_DD_IPCU_INT_MAX ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Ack_Stat_Unit() - INT Ch No is out of range. : Num = %d Ch = %d\n", num, ack_ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( ack == NULL ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Ack_Stat_Unit() - Ack address is NULL. : Num = %d, Ch = %d\n", num, ack_ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	/* Check mode type */
	if( IO_IPCU1.MAILBOX[num].MODE.bit.MODE == E_DD_IPCU_MB_MODE_AUTO_CLEAR ) {
		Ddim_Print(( "Dd_IPCU_Get_MB_Ack_Stat_Unit() - Mode is not correct. : Num = %d\n", num ));
		return D_DD_IPCU_STATUS_ABNORMAL;
	}
	*ack = (1 & (IO_IPCU1.MAILBOX[num].ACKSTAT.word >> ( ack_ch )));
	
	return D_DDIM_OK;
}

/*##################################
  ##  Acknowledge Source Register ##
  ##################################*/
/**
 * @brief	Get Acknowledge source information
 * @param	ULONG num	Mailbox number(0-7)
 * @param	ULONG *ack 	Acknowledge source
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Get_MB_Ack_Src( ULONG num, ULONG *ack )
{
	ULONG mode;
	
#ifdef CO_PARAM_CHECK
	if( num > D_DD_IPCU_MB_MAX ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Ack_Src() - Mailbox number exceeds the maximum. : Num = %d\n", num));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( ack == NULL ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Ack_Src() - Ack address is NULL. : Num = %d\n", num));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	/* Check mode type */
	mode = IO_IPCU1.MAILBOX[num].MODE.bit.MODE;
	if(( mode != E_DD_IPCU_MB_MODE_MANUAL_2 ) && ( mode != E_DD_IPCU_MB_MODE_AUTO_ACK_2 )) {
		Ddim_Print(( "Dd_IPCU_Get_MB_Ack_Src() - Mode is not correct. : Num = %d\n", num ));
		return D_DD_IPCU_STATUS_ABNORMAL;
	}
	*ack = IO_IPCU1.MAILBOX[num].ACKSRC.word;
	
	return D_DDIM_OK;
}

/**
 * @brief	Get Source information indicated by IPCU ch
 * @param	ULONG num		Mailbox number(0-7)
 * @param	UCHAR ack_ch	Interrupt ch of IPCU(12-15)
 * @param	ULONG *ack  	Acknowledge source
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Get_MB_Ack_Src_Unit( ULONG num, ULONG ack_ch, ULONG *ack )
{
	ULONG mode;
	
#ifdef CO_PARAM_CHECK
	if( num > D_DD_IPCU_MB_MAX ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Ack_Src_Unit() - Mailbox number exceeds the maximum. : Num = %d, Ch = %d\n", num, ack_ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( ack_ch > D_DD_IPCU_INT_MAX ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Ack_Src_Unit() - INT Ch No is out of range. : Num = %d Ch = %d\n", num, ack_ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( ack == NULL ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Ack_Src_Unit() - Mailbox address is NULL. : Num = %d, Ch = %d\n", num, ack_ch ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	/* Check mode type */
	mode = IO_IPCU1.MAILBOX[num].MODE.bit.MODE;
	if(( mode != E_DD_IPCU_MB_MODE_MANUAL_2 ) && ( mode != E_DD_IPCU_MB_MODE_AUTO_ACK_2 )) {
		Ddim_Print(( "Dd_IPCU_Get_MB_Ack_Src_Unit() - Mode is not correct. : Num = %d\n", num ));
		return D_DD_IPCU_STATUS_ABNORMAL;
	}
	*ack = (1 & (IO_IPCU1.MAILBOX[num].ACKSRC.word >> ( ack_ch )));
	
	return D_DDIM_OK;
}

/*##################################
  ##         Data Register        ##
  ##################################*/
/**
 * @brief	Get Transfer data
 * @param	ULONG num		Mailbox number(0-7)
 * @param	UCHAR dat_num	Transfer data No.
 * @param	ULONG *data 	Transfer data
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Get_MB_Data( ULONG num, UCHAR dat_num, ULONG *data )
{
#ifdef CO_PARAM_CHECK
	if( num > D_DD_IPCU_MB_MAX ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Data() - Mailbox number exceeds the maximum. : Num = %d, Data No = %d\n", num, dat_num ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( dat_num > D_DD_IPCU_MB_DATA_MAX ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Data() - Transfer data No. exceeds the maximum. : Num = %d, Data No = %d\n", num, dat_num ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( data == NULL ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Data() - Data address is NULL. : Num = %d, Data No = %d\n", num, dat_num ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	*data = IO_IPCU1.MAILBOX[num].DATA[dat_num];
	
	return D_DDIM_OK;
}

/**
 * @brief	Set Transfer data
 * @param	ULONG num		Mailbox number(0-7)
 * @param	UCHAR dat_num	Transfer data No.
 * @param	ULONG data 		Transfer data
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Set_MB_Data( ULONG num, UCHAR dat_num, ULONG data )
{
#ifdef CO_PARAM_CHECK
	if( num > D_DD_IPCU_MB_MAX ){
		Ddim_Print(( "Dd_IPCU_Set_MB_Data() - Mailbox number exceeds the maximum. : Num = %d, Data No = %d\n", num, dat_num ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( dat_num > D_DD_IPCU_MB_DATA_MAX ){
		Ddim_Print(( "Dd_IPCU_Set_MB_Data() - Transfer data No. exceeds the maximum. : Num = %d, Data No = %d\n", num, dat_num ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	IO_IPCU1.MAILBOX[num].DATA[dat_num] = data;
	
	return D_DDIM_OK;
}

/*##################################
  ##    MailBox Status Register   ##
  ##################################*/
/**
 * @brief	Get MailBox status
 * @param	ULONG *mb_stat 	MailBox status
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Get_MB_Stat( ULONG *mb_stat )
{
#ifdef CO_PARAM_CHECK
	if( mb_stat == NULL ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Stat() - MB status address is NULL.\n" ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	*mb_stat = IO_IPCU1.MBSTAT.word;
	
	return D_DDIM_OK;
}

/**
 * @brief	Get MailBox status
 * @param	ULONG num		Mailbox number(0-7)
 * @param	ULONG *mb_stat 	MailBox status
 * @return  D_DDIM_OK / D_DD_IPCU_INPUT_PARAM_ERR
 */
INT32 Dd_IPCU_Get_MB_Stat_MB( ULONG num, ULONG *mb_stat )
{
#ifdef CO_PARAM_CHECK
	if( num > D_DD_IPCU_MB_MAX ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Stat_MB() - Mailbox number exceeds the maximum. : Num = %d\n", num ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
	if( mb_stat == NULL ){
		Ddim_Print(( "Dd_IPCU_Get_MB_Stat_MB() - MB status address is NULL.\n" ));
		return D_DD_IPCU_INPUT_PARAM_ERR;
	}
#endif // CO_PARAM_CHECK
	
	*mb_stat = ( 1 & (IO_IPCU1.MBSTAT.word >> ( num )));
	
	return D_DDIM_OK;
}

#ifdef CO_DDIM_UTILITY_USE
//---------------------------- utility section ---------------------------
// Nothing Special
//---------------------------- colabo section ----------------------------
// Nothing Special

#endif //CO_DDIM_UTILITY_USE

